home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / ka9q / ka9q_src.arc / SMTPCLI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-07-28  |  16.1 KB  |  791 lines

  1. /* smtpcli.c
  2.  *    Client routines for Simple Mail Transfer Protocol ala RFC821
  3.  *    A.D. Barksdale Garbee II, aka Bdale, N3EUA
  4.  *    Copyright 1986 Bdale Garbee, All Rights Reserved.
  5.  *    Permission granted for non-commercial copying and use, provided
  6.  *    this notice is retained.
  7.  *    Modified 14 June 1987 by P. Karn for symbolic target addresses,
  8.  *    also rebuilt locking mechanism
  9.  *    Limit on max simultaneous sessions, reuse of connections - 12/87 NN2Z
  10.  */
  11. #include <stdio.h>
  12. #if (!ATARI_ST || LATTICE)    /* DG2KK */
  13. #include <fcntl.h>
  14. #endif
  15. #include "global.h"
  16. #include "netuser.h"
  17. #include "mbuf.h"
  18. #include "timer.h"
  19. #include "tcp.h"
  20. #include "smtp.h"
  21. #include "trace.h"
  22. #include "cmdparse.h"
  23.  
  24. extern int16 lport;            /* local port placeholder */
  25. extern int32 resolve();
  26. static struct timer smtpcli_t;
  27. int32 gateway;
  28.  
  29. #ifdef SMTPTRACE
  30. int16    smtptrace = 0;            /* used for trace level */
  31. int dosmtptrace();
  32. #endif
  33.  
  34. int16    smtpmaxcli  = MAXSESSIONS;    /* the max client connections allowed */
  35. int16    smtpcli = 0;            /* number of client connections
  36.                     * currently open */
  37.  
  38. static struct smtp_cb *cli_session[MAXSESSIONS]; /* queue of client sessions  */
  39.  
  40. int dosmtptick(),dogateway(),dosmtpmaxcli(),mlock(),dotimer();
  41. void quit(),abort_trans(),rejextjob(),sendit(),del_session(),del_job();
  42. void rejectjob(),execjobs(),smtp_transaction();
  43. struct smtp_cb *newcb(),*lookup();
  44. struct smtp_job *setupjob();
  45.  
  46. struct cmds smtpcmds[] = {
  47.     "gateway",    dogateway,    0,    NULLCHAR,    NULLCHAR,
  48.     "kick",     dosmtptick,    0,    NULLCHAR,    NULLCHAR,
  49.     "maxclients",    dosmtpmaxcli,    0,    NULLCHAR,    NULLCHAR,
  50.     "timer",    dotimer,    0,    NULLCHAR,    NULLCHAR,
  51. #ifdef SMTPTRACE
  52.     "trace",    dosmtptrace,    0,    NULLCHAR,    NULLCHAR,
  53. #endif
  54.     NULLCHAR,    NULLFP,     0,    
  55.     "subcommands: gateway kick maxclients timer trace",
  56.         NULLCHAR,
  57. };
  58.  
  59. dosmtp(argc,argv)
  60. int argc;
  61. char *argv[];
  62. {
  63.     return subcmd(smtpcmds,argc,argv);
  64. }
  65.  
  66. static int
  67. dosmtpmaxcli(argc,argv)
  68. int argc;
  69. char *argv[];
  70. {
  71.     int x;
  72.     if (argc < 2)
  73.         printf("%d\n",smtpmaxcli);
  74.     else {
  75.         x = atoi(argv[1]);
  76.         if (x > MAXSESSIONS)
  77.             printf("max clients must be <= %d\n",MAXSESSIONS);
  78.         else
  79.             smtpmaxcli = x;
  80.     }
  81.     return 0;
  82. }
  83.  
  84. static int
  85. dogateway(argc,argv)
  86. int argc;
  87. char *argv[];
  88. {
  89.     char *inet_ntoa();
  90.     int32 n;
  91.     extern char badhost[];
  92.  
  93.     if(argc < 2){
  94.         printf("%s\n",inet_ntoa(gateway));
  95.     } else if((n = resolve(argv[1])) == 0){
  96.         printf(badhost,argv[1]);
  97.         return 1;
  98.     } else
  99.         gateway = n;
  100.     return 0;
  101. }
  102.  
  103. #ifdef SMTPTRACE
  104. static int
  105. dosmtptrace(argc,argv)
  106. int argc;
  107. char *argv[];
  108. {
  109.     if (argc < 2)
  110.         printf("%d\n",smtptrace);
  111.     else 
  112.         smtptrace = atoi(argv[1]);
  113.     return 0;
  114. }
  115. #endif
  116.  
  117. /* Set outbound spool poll interval */
  118. static int
  119. dotimer(argc,argv)
  120. int argc;
  121. char *argv[];
  122. {
  123.     int dosmtptick();
  124.  
  125.     if(argc < 2){
  126.         printf("%d/%d\n",smtpcli_t.start - smtpcli_t.count,
  127.         smtpcli_t.start);
  128.         return 0;
  129.     }
  130.     smtpcli_t.func = (void (*)())dosmtptick;/* what to call on timeout */
  131.     smtpcli_t.arg = NULLCHAR;        /* dummy value */
  132.     smtpcli_t.start = atoi(argv[1]);    /* set timer duration */
  133.     start_timer(&smtpcli_t);        /* and fire it up */
  134.     return 0;
  135. }
  136.  
  137. /* this is the routine that gets called every so often to do outgoing mail
  138.    processing */
  139. int
  140. dosmtptick()
  141. {
  142.     register struct smtp_cb *cb;
  143.     char    tmpstring[LINELEN], wfilename[13], prefix[9];
  144.     char    from[LINELEN], to[LINELEN];
  145.     char *cp, *cp1;
  146.     int32 destaddr;
  147.     FILE *wfile;
  148.  
  149. #ifdef SMTPTRACE
  150.     if (smtptrace > 5) {
  151.         printf("smtp daemon entered\n");
  152.         fflush(stdout);
  153.     }
  154. #endif
  155.     for(filedir(mailqueue,0,wfilename);wfilename[0] != '\0';
  156.         filedir(mailqueue,1,wfilename)){
  157.  
  158.         /* save the prefix of the file name which it job id */
  159.         cp = wfilename;
  160.         cp1 = prefix;
  161.         while (*cp && *cp != '.')
  162.             *cp1++ = *cp++;
  163.         *cp1 = '\0';
  164.  
  165.         /* lock this file from the smtp daemon */
  166.         if (mlock(mailqdir,prefix))
  167.             continue;
  168.  
  169.         sprintf(tmpstring,"%s%s",mailqdir,wfilename);
  170.         if ((wfile = fopen(tmpstring,"r")) == NULLFILE) {
  171.             /* probably too many open files */
  172.             (void) rmlock(mailqdir,prefix);
  173.             /* continue to next message. The failure
  174.             * may be temporary */
  175.             continue;
  176.         }
  177.  
  178.         fgets(tmpstring,LINELEN,wfile); /* read target host */
  179.         rip(tmpstring);
  180.         fgets(from,LINELEN,wfile);    /* read target host */
  181.         rip(from);
  182.         fgets(to,LINELEN,wfile);    /* read target user */
  183.         rip(to);
  184.         fclose(wfile);
  185.  
  186.         if ((destaddr = mailroute(tmpstring)) == 0) {
  187.             printf("** smtpcli: Unknown address %s\n",tmpstring);
  188.             fflush(stdout);
  189.             (void) rmlock(mailqdir,prefix);
  190.             continue;
  191.         }
  192.  
  193.         if ((cb = lookup(destaddr)) == NULLCB) {
  194.             /* there are enough processes running already */
  195.             if (smtpcli >= smtpmaxcli) {
  196. #ifdef SMTPTRACE
  197.                 if (smtptrace) {
  198.                     printf("smtp daemon: too many processes\n");
  199.                     fflush(stdout);
  200.                 }
  201. #endif
  202.                     
  203.                 (void) rmlock(mailqdir,prefix);
  204.                 break;
  205.             }
  206.             if ((cb = newcb()) == NULLCB) {
  207.                 (void) rmlock(mailqdir,prefix);
  208.                 break;
  209.             } 
  210.             cb->ipaddr = destaddr;
  211.         } else {
  212.             /* This system is already is sending mail lets not
  213.             * interfere with its send queue.
  214.             */
  215.             if (cb->state != CLI_IDLE) {
  216.                 (void) rmlock(mailqdir,prefix);
  217.                 continue;
  218.             }
  219.         }
  220. #ifdef SMTPTRACE
  221.         if (smtptrace > 1) {
  222.             printf("queue job %s To: %s From: %s\n",prefix,to,from);
  223.             fflush(stdout);
  224.         }
  225. #endif
  226.  
  227.         if (setupjob(cb,prefix,to,from) == NULLJOB) {
  228.             (void) rmlock(mailqdir,prefix);
  229.             del_session(cb);
  230.             break;
  231.         }
  232.     }
  233.  
  234.     /* start sending that mail */
  235.     execjobs();
  236.  
  237.     /* Restart timer */
  238.     start_timer(&smtpcli_t);
  239. #ifdef SMTPTRACE
  240.     if (smtptrace > 5) {
  241.         printf("smtp daemon done\n");
  242.         fflush(stdout);
  243.     }
  244. #endif
  245. }
  246.  
  247. /* this is the master state machine that handles a single SMTP transaction */
  248. void
  249. smtp_transaction(cb)
  250. struct smtp_cb *cb;
  251. {
  252.     void smtp_cts();
  253.     char reply;
  254.     int rcode;
  255.  
  256. #ifdef SMTPTRACE
  257.     if (smtptrace > 7) 
  258.         printf("smtp_transaction() enter state=%u\n",cb->state);
  259.     if (smtptrace) {
  260.         printf("%s\n",cb->buf);
  261.         fflush(stdout);
  262.     }
  263. #endif
  264.     /* Another line follows; ignore this one */
  265.     if(cb->buf[0] == '0' || cb->buf[3] == '-')
  266.         return;
  267.  
  268.     reply = cb->buf[0];
  269.     rcode = atoi(cb->buf);
  270.  
  271.     /* if service shuting down */
  272.     if (rcode == 421) {
  273.         quit(cb);
  274.         return;
  275.     }
  276.  
  277.     switch(cb->state) {
  278.     case CLI_OPEN_STATE:
  279.         if (reply != '2')
  280.             quit(cb);
  281.         else {
  282.             cb->state = CLI_HELO_STATE;
  283.             sendit(cb,"HELO %s\r\n",hostname);
  284.         }
  285.         break;
  286.     case CLI_HELO_STATE:
  287.         if (reply != '2')
  288.             quit(cb);
  289.         else {
  290.             cb->state = CLI_MAIL_STATE;
  291.             /* send both to speed things up */
  292.             sendit(cb,"MAIL FROM:<%s>\r\nRCPT TO:<%s>\r\n",
  293.                 cb->jobq->from,cb->jobq->to);
  294.         }
  295.         break;            
  296.     case CLI_MAIL_STATE:
  297.         if (reply != '2')
  298.             quit(cb);
  299.         else {
  300.             cb->state = CLI_RCPT_STATE;
  301.             /* the RCPT is sent already */
  302.         }
  303.         break;
  304.     case CLI_RCPT_STATE:
  305.         if (reply == '5') {
  306.             rejectjob(cb);
  307.             abort_trans(cb);
  308.         } else if (reply != '2')
  309.             abort_trans(cb);
  310.         else {
  311.             /* open text file here because it will be too
  312.             * late to abort in the data state.
  313.             */
  314.             /* if this file open fails abort */
  315.             if ((cb->tfile = fopen(cb->tname,"r")) == NULLFILE)
  316.                 abort_trans(cb);
  317.             else {
  318.                 cb->state = CLI_DATA_STATE;
  319.                 sendit(cb,"DATA\r\n");
  320.             }
  321.         }
  322.         break;
  323.     case CLI_DATA_STATE:
  324.         if (reply != '3')
  325.             abort_trans(cb);
  326.         else {
  327.             cb->state = CLI_SEND_STATE;
  328.             /* Kick the data transfer to get it started */
  329.             smtp_cts(cb->tcb,cb->tcb->window - cb->tcb->sndcnt);
  330.         }
  331.         break;
  332.     case CLI_SEND_STATE:
  333.         /* the transmitter upcall routine will advance the
  334.            state pointer on end of file, so we do nada... */
  335.         break;
  336.     case CLI_UNLK_STATE:
  337.         if (reply == '5') {
  338.             rejectjob(cb);
  339.             abort_trans(cb);
  340.         } else if (reply != '2')
  341.             abort_trans(cb);
  342.         else {
  343.             unlink(cb->wname);    /* unlink workfile */
  344.             /* close and unlink the textfile */
  345.             if(cb->tfile != NULLFILE) {
  346.                 fclose(cb->tfile);
  347.                 cb->tfile = NULLFILE;
  348.             }
  349.             unlink(cb->tname);
  350.             abort_trans(cb);
  351.         }
  352.         break;
  353.     case CLI_QUIT_STATE:
  354.         close_tcp(cb->tcb); /* close up connection */
  355.         break;
  356.     }
  357. }
  358.  
  359. /* abort the currrent job. Remove the lockfile.
  360.  * If more work exists set up the next job if
  361.  * not then shut down.
  362. */
  363. static void
  364. abort_trans(cb)
  365. struct smtp_cb *cb;
  366. {
  367.     if(cb->tfile != NULLFILE) {
  368.         fclose(cb->tfile);
  369.         cb->tfile = NULLFILE;
  370.     }
  371.     (void) rmlock(mailqdir,cb->jobq->jobname);
  372.     if (nextjob(cb)) {
  373.         sendit(cb,"RSET\r\n");
  374.         cb->state = CLI_HELO_STATE;
  375.     } else {
  376.         sendit(cb,"QUIT\r\n");        /* issue a quit command */
  377.         cb->state = CLI_QUIT_STATE;
  378.     }
  379. }
  380.  
  381. /* close down link after a failure */
  382. static void
  383. quit(cb)
  384. struct smtp_cb *cb;
  385. {
  386.     cb->state = CLI_QUIT_STATE;
  387.     sendit(cb,"QUIT\r\n");        /* issue a quit command */
  388. }
  389.  
  390. /* smtp receiver upcall routine.  fires up the state machine to parse input */
  391. static
  392. void
  393. smtp_rec(tcb,cnt)
  394. struct tcb *tcb;
  395. int16 cnt;
  396. {
  397.     register struct smtp_cb *cb;
  398.     char *inet_ntoa(), c;
  399.     struct mbuf *bp;
  400.  
  401. #ifdef SMTPTRACE
  402.     if (smtptrace > 5)  {
  403.         printf("smtp_rec called\n");
  404.         fflush(stdout);
  405.     }
  406. #endif
  407.     cb = (struct smtp_cb *)tcb->user;    /* point to our struct */
  408.     recv_tcp(tcb,&bp,cnt);    /* suck up chars from low level routine */
  409.  
  410.     /* Assemble input line in buffer, return if incomplete */
  411.     while(pullup(&bp,&c,1) == 1) {
  412.         switch(c) {
  413.         case '\r':    /* strip cr's */
  414.             continue;
  415.         case '\n':    /* line is finished, go do it! */
  416.             cb->buf[cb->cnt] = '\0';
  417.             smtp_transaction(cb);
  418.             cb->cnt = 0;
  419.             break;
  420.         default:    /* other chars get added to buffer */
  421.             if(cb->cnt != LINELEN-1)
  422.                 cb->buf[cb->cnt++] = c;
  423.             break;
  424.         }
  425.     }
  426. }
  427.  
  428. /* smtp transmitter ready upcall routine.  twiddles cts flag */
  429. static 
  430. void
  431. smtp_cts(tcb,cnt)
  432. struct tcb *tcb;
  433. int16 cnt;
  434. {
  435.     register struct smtp_cb *cb;
  436.     struct mbuf *bp;
  437.     char *cp;
  438.     int c;
  439.  
  440. #ifdef SMTPTRACE
  441.     if (smtptrace > 5) {
  442.         printf("smtp_cts called avail %d\n",cnt);
  443.         fflush(stdout);
  444.     }
  445. #endif
  446.     cb = (struct smtp_cb *)tcb->user;    /* point to our struct */
  447.  
  448.     /* don't do anything until/unless we're supposed to be sending */
  449.     if(cb->state != CLI_SEND_STATE)
  450.         return;
  451.  
  452.     if((bp = alloc_mbuf(cnt)) == NULLBUF){
  453.         /* Hard to know what to do here */
  454.         return;
  455.     }
  456.     cp = bp->data;
  457.     while(cnt > 1 && (c = getc(cb->tfile)) != EOF){
  458. #if    (ATARI_ST)
  459.         if (c == '\n') {
  460.             *cp++ = '\r';
  461.             bp->cnt++;
  462.             cnt--;
  463.         }
  464. #endif
  465.  
  466.         *cp++ = c;
  467.         bp->cnt++;
  468.         cnt--;
  469.     }
  470.     if(bp->cnt != 0)
  471.         send_tcp(tcb,bp);
  472.     else
  473.         free_p(bp);
  474.  
  475.     if(cnt > 1){    /* EOF seen */
  476.         sendit(cb,"\r\n.\r\n");
  477.         cb->state = CLI_UNLK_STATE;
  478.     }
  479. }
  480.  
  481. /* smtp state change upcall routine. */
  482. static
  483. void
  484. smtp_state(tcb,old,new)
  485. struct tcb *tcb;
  486. char old,new;
  487. {
  488.     register struct smtp_cb *cb;
  489.     extern char *tcpstates[];
  490.  
  491. #ifdef SMTPTRACE
  492.     if (smtptrace > 5) {
  493.         printf("smtp_state called: %s\n",tcpstates[new]);
  494.         fflush(stdout);
  495.     }
  496. #endif
  497.     cb = (struct smtp_cb *)tcb->user;
  498.     switch(new) {
  499.     case ESTABLISHED:
  500.         cb->state = CLI_OPEN_STATE;    /* shouldn't be needed */
  501.         break;
  502.     case CLOSE_WAIT:
  503.         close_tcp(tcb);         /* shut things down */
  504.         break;
  505.     case CLOSED:
  506.         /* if this close was not done by us ie. a RST */
  507.         if (cb->state != CLI_QUIT_STATE) {
  508.             if(cb->tfile != NULLFILE)
  509.                 fclose(cb->tfile);
  510.         }
  511.         del_session(cb);
  512.         del_tcp(tcb);
  513.         break;
  514.     }
  515. }
  516.  
  517. /* Send message back to server */
  518. /*VARARGS*/
  519. static void
  520. sendit(cb,fmt,arg1,arg2)
  521. struct smtp_cb *cb;
  522. char *fmt,*arg1,*arg2;
  523. {
  524.     struct mbuf *bp,*qdata();
  525.     char tmpstring[256];
  526.  
  527. #ifdef SMTPTRACE
  528.     if (smtptrace) {
  529.         printf(">>> ");
  530.         printf(fmt,arg1,arg2);
  531.         fflush(stdout);
  532.     }
  533. #endif
  534.     sprintf(tmpstring,fmt,arg1,arg2);
  535.     bp = qdata(tmpstring,(int16)strlen(tmpstring));
  536.     send_tcp(cb->tcb,bp);
  537. }
  538.  
  539. /* create mail lockfile */
  540. int
  541. mlock(dir,id)
  542. char *dir,*id;
  543. {
  544.     char lockname[LINELEN];
  545.     int fd;
  546.     /* Try to create the lock file in an atomic operation */
  547.     sprintf(lockname,"%s%s.lck",dir,id);
  548. #if (ATARI_ST && !LATTICE)    /* DG2KK */
  549.     if(!access(lockname,0) || (fd = creat(lockname, 0666)) == -1)
  550.         return -1;
  551. #else
  552.     if((fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0666)) == -1)
  553.         return -1;
  554. #endif
  555.     close(fd);
  556.     return 0;
  557. }
  558.  
  559. /* remove mail lockfile */
  560. int
  561. rmlock(dir,id)
  562. char *dir,*id;
  563. {
  564.     char lockname[LINELEN];
  565.     sprintf(lockname,"%s%s.lck",dir,id);
  566.     return(unlink(lockname));
  567. }
  568.  
  569. /* free the message struct and data */
  570. static void
  571. del_session(cb)
  572. register struct smtp_cb *cb;
  573. {
  574.     register int i;
  575.     register struct smtp_job *jp,*tp;
  576.  
  577.     if (cb == NULL)
  578.         return;
  579.     for(i=0; i<MAXSESSIONS; i++) 
  580.         if(cli_session[i] == cb) {
  581.             cli_session[i] = NULLCB;
  582.             break;
  583.         }
  584.  
  585.     if(cb->wname != NULLCHAR)
  586.         free(cb->wname);
  587.     if(cb->tname != NULLCHAR)
  588.         free(cb->tname);
  589.     for (jp = cb->jobq; jp != NULLJOB;jp = tp) {
  590.             tp = jp->next;
  591.             (void) rmlock(mailqdir,jp->jobname);
  592.             del_job(jp);
  593.     }
  594.     free((char *)cb);
  595.     smtpcli--;    /* number of connections active */
  596. }
  597.  
  598. void
  599. del_job(jp)
  600. register struct smtp_job *jp;
  601. {
  602.     if(jp->to != NULLCHAR)
  603.         free(jp->to);
  604.     if(jp->from != NULLCHAR)
  605.         free(jp->from);
  606.     free((char *)jp);
  607. }
  608.  
  609. /* move a bad job out of the send queue into a holding area */
  610. static void
  611. rejectjob(cb)
  612. struct smtp_cb *cb;
  613. {
  614.     char dest[LINELEN];
  615. #ifdef SMTPTRACE
  616.     if (smtptrace > 5) {
  617.         printf("smtp job %s rejected\n",cb->wname);
  618.         fflush(stdout);
  619.     }
  620. #endif
  621.     /* remove job from queue and save for admin */
  622.     sprintf(dest,"%s%s.txt",baddir,cb->jobq->jobname);
  623.     (void) rename(cb->tname,dest);
  624.     strcpy(rindex(dest,'.'),".wrk");
  625.     (void) rename(cb->wname,dest);
  626.     (void) rmlock(mailqdir,cb->jobq->jobname);
  627. }
  628.  
  629. /* look to see if a smtp control block exists for this ipaddr */
  630. static struct smtp_cb *
  631. lookup(destaddr)
  632. int32 destaddr;
  633. {
  634.     register int i;
  635.  
  636.     for(i=0; i<MAXSESSIONS; i++) {
  637.         if (cli_session[i] == NULLCB)
  638.             continue;
  639.         if (cli_session[i]->ipaddr == destaddr)
  640.             return cli_session[i];
  641.     }
  642.     return NULLCB;
  643. }
  644.  
  645. /* create a new  smtp control block */
  646. static struct smtp_cb *
  647. newcb()
  648. {
  649.     register int i;
  650.     struct smtp_cb *cb;
  651.  
  652.     for(i=0; i<MAXSESSIONS; i++) {
  653.         if(cli_session[i] == NULLCB) {
  654.             cb = (struct smtp_cb *)calloc(1,sizeof(struct smtp_cb));
  655.             if (cb == NULLCB)
  656.                 return(NULLCB);
  657.             cb->wname = malloc((unsigned)strlen(mailqdir) + JOBNAME);
  658.             if (cb->wname == NULLCHAR) {
  659.                 free((char *)cb);
  660.                 return(NULLCB);
  661.             }
  662.             cb->tname = malloc((unsigned)strlen(mailqdir) + JOBNAME);
  663.             if (cb->tname == NULLCHAR) {
  664.                 free(cb->wname);
  665.                 free((char *)cb);
  666.                 return(NULLCB);
  667.             }
  668.             cb->state = CLI_IDLE;
  669.             cli_session[i] = cb;
  670.             smtpcli++;    /* number of connections active */
  671.             return(cb);
  672.         }
  673.     }
  674.     return NULLCB;
  675. }
  676.  
  677. static void
  678. execjobs()
  679. {
  680.     struct socket lsocket, fsocket;
  681.     void smtp_rec(), smtp_cts(), smtp_state();
  682.     register struct smtp_cb *cb;
  683.     int i;
  684.  
  685.     for(i=0; i<MAXSESSIONS; i++) {
  686.         cb = cli_session[i];
  687.         if (cb == NULLCB) 
  688.             continue;
  689.         if(cb->state != CLI_IDLE)
  690.             continue;
  691.  
  692.         sprintf(cb->tname,"%s%s.txt",mailqdir,cb->jobq->jobname);
  693.         sprintf(cb->wname,"%s%s.wrk",mailqdir,cb->jobq->jobname);
  694.  
  695.         /* setup the socket */
  696.         fsocket.address = cb->ipaddr;
  697.         fsocket.port = SMTP_PORT;
  698.         lsocket.address = ip_addr;    /* our ip address */
  699.         lsocket.port = lport++;     /* next unused port */
  700. #ifdef SMTPTRACE
  701.         if (smtptrace) {
  702.             printf("Trying Connection to %s\n",inet_ntoa(fsocket.address));
  703.             fflush(stdout);
  704.         }
  705. #endif
  706.  
  707.         /* open smtp connection */
  708.         cb->state = CLI_OPEN_STATE;    /* init state placeholder */
  709.         cb->tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,tcp_window,
  710.             smtp_rec,smtp_cts,smtp_state,0,(char *)cb);
  711.         cb->tcb->user = (char *)cb;    /* Upward pointer */
  712.     }
  713. }
  714.     
  715. /* add this job to control block queue */
  716. struct smtp_job *
  717. setupjob(cb,id,to,from)
  718. struct smtp_cb *cb;
  719. char *id,*to,*from;
  720. {
  721.     register struct smtp_job *p1,*p2;
  722.  
  723.     p1 = (struct smtp_job *)calloc(1,sizeof(struct smtp_job));
  724.     if (p1 == NULLJOB)
  725.         return NULLJOB;
  726.     p1->to = malloc((unsigned)strlen(to) + 1);
  727.     if (p1->to == NULLCHAR) {
  728.         free((char *)p1);
  729.         return NULLJOB;
  730.     }
  731.     p1->from = malloc((unsigned)strlen(from) + 1);
  732.     if (p1->from == NULLCHAR) {
  733.         free(p1->to);
  734.         free((char *)p1);
  735.         return NULLJOB;
  736.     }
  737.     strcpy(p1->to,to);
  738.     strcpy(p1->from,from);
  739.     strcpy(p1->jobname,id);
  740.     if ((p2 = cb->jobq) == NULLJOB)
  741.         cb->jobq = p1;
  742.     else {
  743.         while(p2->next != NULLJOB)
  744.             p2 = p2->next;
  745.         p2->next = p1;
  746.     }
  747.     return p1;
  748. }
  749.  
  750. /* called to advance to the next job */
  751. static int
  752. nextjob(cb)
  753. struct smtp_cb *cb;
  754. {
  755.     struct smtp_job *jp;
  756.     jp = cb->jobq->next;
  757.     del_job(cb->jobq);
  758.     if (jp == NULLJOB) {
  759.         cb->jobq = NULLJOB;
  760.         return 0;
  761.     }
  762.     cb->jobq = jp;
  763.     sprintf(cb->tname,"%s%s.txt",mailqdir,cb->jobq->jobname);
  764.     sprintf(cb->wname,"%s%s.wrk",mailqdir,cb->jobq->jobname);
  765. #ifdef SMTPTRACE
  766.     if (smtptrace > 5) {
  767.         printf("sending %s\n",cb->jobq->jobname);
  768.         fflush(stdout);
  769.     }
  770. #endif
  771.         return 1;
  772.  
  773. }
  774.  
  775.  
  776. /* mail routing funtion. For now just used the hosts file */
  777. int32
  778. mailroute(dest)
  779. char *dest;
  780. {
  781.     int32 destaddr;
  782.  
  783.     /* look up address or use the gateway */
  784.     if ((destaddr = resolve(dest)) == 0)
  785.         if (gateway != 0) 
  786.             destaddr = gateway; /* Use the gateway    */
  787.     return destaddr;
  788.     
  789. }
  790.  
  791.